package com.seashop.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.seashop.config.PropertiesConfig;
import com.seashop.constant.RedisConstant;
import com.seashop.entity.AllUser;
import com.seashop.entity.MemberRelation;
import com.seashop.entity.User;
import com.seashop.entity.UserInviteRecord;
import com.seashop.enums.ActiveProfileEnum;
import com.seashop.enums.UserTypeEnum;
import com.seashop.feign.ThirdFeignClient;
import com.seashop.mapper.AllUserMapper;
import com.seashop.mapper.UserInviteRecordMapper;
import com.seashop.mapper.UserMapper;
import com.seashop.redis.RedisZero;
import com.seashop.request.LoginRequestParam;
import com.seashop.request.MemberSearchParam;
import com.seashop.request.UpdateUserRequestParam;
import com.seashop.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.seashop.util.*;
import org.springframework.beans.factory.annotation.Value;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 前台用户表 服务实现类
 * </p>
 *
 * @author moredln
 * @since 2020-11-21
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Value("${system.mobileList}")
    private List<String> mobileList;
    @Value("${system.defaultCode}")
    private String defaultCode;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private AllUserMapper allUserMapper;
    @Autowired
    private UserInviteRecordMapper userInviteRecordMapper;
    @Autowired
    private RedisZero redisZero;
    @Autowired
    private ThirdFeignClient thirdFeignClient;
    @Autowired
    private SmsLimitUtils smsLimitUtils;

    @Override
    public IPage<User> listUserPage(MemberSearchParam param) {
        Page<User> page = new Page<>(param.getCurrent(), param.getSize());
        QueryWrapper<User> wrapper = new QueryWrapper<User>();
        wrapper.eq("country_code", param.getCountryCode());
        if (StringUtils.isNotEmpty(param.getUserName())) {
            wrapper.like("username", param.getUserName());
        }
        if (StringUtils.isNotEmpty(param.getMobile())) {
            wrapper.like("mobile", param.getMobile());
        }
        if (null != param.getUserId()) {
            wrapper.eq("userid", param.getUserId());
        }
        wrapper.orderByDesc("create_time").orderByDesc("last_login_time");
        return userMapper.selectPage(page, wrapper);
    }

    @Override
    public int getVerificationCode(String mobile, String areaCode, String countryCode) {
        Integer status = 3;
        String verifyCode;
        String key = RedisConstant.MSG_CODE_PREFIX + areaCode + mobile;
        try {
            if (redisZero.exists(key)) {
                verifyCode = redisZero.get(key).toString();
                log.info("Redis获取验证码：" + verifyCode);
            } else {
                // 验证码写入redis,并设置失效时间
                verifyCode = RandomUtil.getRandom(4);
                // 发送验证码到手机
                if (mobileList.contains(mobile)) {
                    verifyCode = defaultCode;
                } else {
                    // 判断短信限制是否存在，不存在则是Manage管理系统没有初始化system_config表到Redis
                    if (!redisZero.exists(RedisConstant.SMS_LIMIT)) {
                        log.error("Manage管理系统没有初始化system_config表到Redis");
                        return 0;
                    }
                    // 增加发送送次数限制
                    JSONObject smsLimit = smsLimitUtils.checkSmsLimit(areaCode + mobile);
                    status = smsLimit.getInteger("status");
                    String msgMobile = MessageUtil.handleMobile(areaCode + mobile);
                    String msgTemplate = MessageUtil.getMessageTemplate(countryCode);
                    String runtime = PropertiesConfig.getActiveProfile();
                    // 生产发送短信
                    if (ActiveProfileEnum.PROD.getName().equals(runtime)) {
                        thirdFeignClient.sendMessage(verifyCode, msgMobile, msgTemplate);
                    }
                }
                redisZero.setex(key, verifyCode, 5, TimeUnit.MINUTES);
                log.info("Redis存储验证码成功");
            }
        } catch (Exception e) {
            log.error("短信发送异常：" + e.getMessage());
            return 0;
        }
        return status;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int register(LoginRequestParam param) {
        String referralCode = param.getReferralCode();
        String mobile = param.getMobile();
        String areaCode = param.getAreaCode();
        User user = new User();
        user.setMobile(areaCode + mobile);
        user.setCountryCode(param.getCountryCode());
        user.setNowCountryCode(param.getCountryCode());
        user.setPlatform(param.getPlatform());
        user.setLanguageType(param.getLanguageType());
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        user.setStatus(1);
        user.setLastLoginTime(LocalDateTime.now());
        try {
            // 1：保存用户表
            int userNum = userMapper.insert(user);
            if (userNum < 1) {
                log.info("保存user信息失败");
                return 0;
            }
            // 2:保存所有用户
            int allUserNum = this.saveAllUser(user);
            if (allUserNum < 1) {
                log.info("保存all_user信息失败");
                return 0;
            }
            if (StringUtils.isNotEmpty(referralCode)) {
                User parentUser = userMapper.selectOne(new QueryWrapper<User>().eq("referral_code", referralCode));
                // 会员制邀请码逻辑
                if (null != parentUser) {
                    Integer parentId = parentUser.getUserId();
                }
                // 创建自己的推荐码
                String referralCodeSelf = ReferralCodeUtil.getReferralCode();
                user.setReferralCode(referralCodeSelf);
                List<AllUser> allUsers = allUserMapper.selectList(new QueryWrapper<AllUser>().eq("referral_code", referralCode));
                if (!allUsers.isEmpty()) {
                    user.setAdminId(allUsers.get(0).getAllUserId());
                    user.setAdminName(allUsers.get(0).getAllUserName());
                }
                // 更新用户表
                int updateUserNum = userMapper.updateById(user);
                if (updateUserNum < 1) {
                    log.info("更新user信息失败");
                    return 0;
                }
                // 3:保存会员邀请记录
                int userInviteRecordNum = this.saveUserInviteRecord(user, parentUser.getUserId());
                if (userInviteRecordNum < 1) {
                    log.info("保存user_invite_record信息失败");
                    return 0;
                }
            }
            // 4：添加Redis用户节点树
//            this.AddUserTreeRedis();
            // 5:保存会员关系
            this.saveMemberRelation(user);
        } catch (Exception e) {
            log.error("用户注册失败：{}", e.getMessage());
            return 0;
        }
        return 1;
    }

    private void saveMemberRelation(User user) {
        MemberRelation memberRelation = new MemberRelation();
        memberRelation.setParentId(-1);
        if (StringUtils.isNotEmpty(user.getReferralCode())) {
            User parentUser = userMapper.selectOne(new QueryWrapper<User>().eq("referral_code", user.getReferralCode()));
            memberRelation.setParentId(parentUser.getUserId());
        }
        memberRelation.setUserLevel(1);
        memberRelation.setCountryCode(user.getCountryCode());
        memberRelation.setBindTime(LocalDateTime.now());
    }

    private int saveUserInviteRecord(User user, Integer inviteId) {
        UserInviteRecord userInviteRecord = new UserInviteRecord();
        userInviteRecord.setCountryCode(user.getCountryCode());
        userInviteRecord.setInvitePeopleId(inviteId);
        userInviteRecord.setInviteesId(user.getUserId());
        userInviteRecord.setInviteesName(user.getUserName());
        userInviteRecord.setInviteesMobile(user.getMobile());
        return userInviteRecordMapper.insert(userInviteRecord);
    }

    private int saveAllUser(User user) {
        AllUser allUser = new AllUser();
        allUser.setAllUserId(user.getUserId());
        allUser.setAllUserName(user.getUserName());
        allUser.setCountryCode(user.getCountryCode());
        allUser.setUserType(UserTypeEnum.MEMBER_USER.name());
        allUser.setReferralCode(user.getReferralCode());
        return allUserMapper.insert(allUser);
    }

    @Override
    public String updateToken(Integer userid) {
        // 随机生成一个token
        String token = MD5Util.MD5Encode(userid + new Date().toString(), null);
        // 存储token到Redis
        String key = String.format(RedisConstant.USER_BASE_TOKEN, userid);
        redisZero.setex(key, token, 7, TimeUnit.DAYS);
        log.info("Redis存储token:" + token);
        return token;
    }

    @Override
    public Integer updateUserInfo(User user, UpdateUserRequestParam param) {
        // 更改头像
        if (StringUtils.isNotEmpty(param.getAvatar())) {
            user.setAvatar(param.getAvatar());
        }
        // 更改用户姓名
        if (StringUtils.isNotEmpty(param.getUserName())) {
            user.setUserName(param.getUserName());
        }
        // 更改用户性别
        if (StringUtils.isNotEmpty(param.getSex())) {
            user.setSex(param.getSex());
        }
        // 更改用户生日
        if (null != param.getBirthday()) {
            user.setBirthday(param.getBirthday());
        }
        // 更改邮箱
        if (StringUtils.isNotEmpty(param.getEmail())) {
            user.setEmail(param.getEmail());
        }
        return userMapper.updateById(user);
    }

}
